﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace ecdl.demo.persistence {
    public abstract class DTODeserializer {

        public XmlAttributeOverrides AttributeOverrides { get; set; }
        public ISet<Type> Types { get; set; }


        private List<XmlElementAttribute> expressionElementAttributes = new List<XmlElementAttribute>();
        private List<XmlElementAttribute> preConditionElementAttributes = new List<XmlElementAttribute>();
        private List<XmlElementAttribute> taskElementAttributes = new List<XmlElementAttribute>();
        public DTODeserializer() {
            AttributeOverrides = new XmlAttributeOverrides();
            Types = new HashSet<Type>();

        }

        protected abstract void RegisterTypes();

        protected abstract void AddOverrides();

        public void AddExpressionElementAttribute(Type type, string elementName) {
            AddType(type);
            expressionElementAttributes.Add(new XmlElementAttribute(elementName, type));
        }

        public void AddPreconditionElementAttribute(Type type, string elementName) {
            preConditionElementAttributes.Add(new XmlElementAttribute(elementName, type));
        }

        public void AddTaskElementAttribute(Type type, string elementName) {
            taskElementAttributes.Add(new XmlElementAttribute(elementName, type));
        }

        public XmlAttributes GetExpressionXmlElementAttributes() {
            return GetXmlAttributeFor(expressionElementAttributes);
        }

        public XmlAttributes GetExpressionXmlArrayAttributes() {
            return GetXmlArrayAttributeFor(expressionElementAttributes);
        }

        public XmlAttributes GetPreconditionXmlElementAttribute() {
            return GetXmlAttributeFor(preConditionElementAttributes);
        }

        public XmlAttributes GetPreconditionXmlArrayAttributes() {
            return GetXmlArrayAttributeFor(preConditionElementAttributes);
        }

        public XmlAttributes GetTaskXmlElementAttribute() {
            return GetXmlAttributeFor(taskElementAttributes);
        }

        public XmlAttributes GetTaskXmlArrayAttributes() {
            return GetXmlArrayAttributeFor(taskElementAttributes);
        }

        private XmlAttributes GetXmlAttributeFor(IEnumerable<XmlElementAttribute> elementAttributes) {
            XmlAttributes attributes = new XmlAttributes();
            foreach (var item in elementAttributes) {
                attributes.XmlElements.Add(item);
            }
            return attributes;
        }


        private XmlAttributes GetXmlArrayAttributeFor(IEnumerable<XmlElementAttribute> elementAttributes) {
            XmlAttributes attributes = new XmlAttributes();
            foreach (var item in elementAttributes) {
                attributes.XmlArrayItems.Add(new XmlArrayItemAttribute(item.ElementName, item.Type));
            }
            return attributes;
        }

        public void AddAttributeOverride(Type type, string member, XmlAttributes xmlAttributes) {
            AddType(type);
            AttributeOverrides.Add(type, member, xmlAttributes);
        }

        public void AddType(Type type) {
            Types.Add(type);
        }

        protected XmlSerializer CreateSerializer() {
            RegisterTypes();
            AddOverrides();
            return new XmlSerializer(GetRootType(), AttributeOverrides, Types.ToArray<Type>() , null, null);
        }

        protected abstract Type GetRootType();

    }
}
